﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using NakedObjects;
using NakedObjects.Services;

namespace FUFDomain.Undo
{
    [NotPersisted]
    public class UndoManager : AbstractService
    {
        private Dictionary<String, Stack<IUndoCopy>> registro = new Dictionary<String, Stack<IUndoCopy>>();
        private Dictionary<String, IUndoCopy> infoActual = new Dictionary<String, IUndoCopy>();

        public virtual void IniUndoObject(IUndo dat)
        {
            if (! registro.ContainsKey(dat.UndoKey()) ) {
                registro.Add(dat.UndoKey(), new Stack<IUndoCopy>());
            }
            infoActual[dat.UndoKey()] = dat.UndoCopy();
        }

        [Hidden]
        public void SaveChange( IUndo dat )
        {
            if (!registro.ContainsKey(dat.UndoKey()))
            {
                registro.Add(dat.UndoKey(), new Stack<IUndoCopy>());
            }
            AddToStack(registro[dat.UndoKey()], dat.UndoCopy());
        }

        [Hidden]
        public virtual void UndoObject(IUndo dat)
        {
            if (registro[dat.UndoKey()].Count > 0)
            {
                IUndoCopy info = registro[dat.UndoKey()].Pop();
                dat.UndoCopy(info);
            }            
        }
        
        [Hidden]
        public virtual bool IsUndoObject(IUndoCopy dat)
        {
            return this.registro[dat.UndoKey()].Count > 0;
        }

        #region Privados

        private void AddToStack(Stack<IUndoCopy> stack, IUndoCopy dat)
        {

            if (stack.Count >= 10)
            {
                stack.Reverse();
                stack.Pop();
                stack.Reverse();
            }

            if (!dat.UndoEquals(infoActual[dat.UndoKey()]))
            {
                stack.Push(infoActual[dat.UndoKey()]);
            }
            infoActual[dat.UndoKey()] = dat;
        }

        #endregion


    }
}
